<!-- 上传 -->
<template>
  <div>
    <el-button type="primary" @click="openDialog()">上传</el-button>
    <el-dialog v-model="dialogVisible" title="上传" width="500">
      <el-form :model="form">
        <el-form-item label="选项">
          <el-select
            v-model="form.option"
            placeholder="请选择"
            @change="handleChange"
          >
            <el-option
              v-for="item in options"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="位置">
          <el-form :inline="true" :model="dirQuery">
            <el-form-item>
              <!-- 文件夹显示 -->
              <el-breadcrumb :separator-icon="ArrowRight">
                <el-breadcrumb-item
                  v-for="(item, index) in fileDir"
                  :key="index"
                >
                  <el-link
                    :underline="false"
                    @click="handleCrumbClick(item, index)"
                  >
                    {{ item }}
                  </el-link>
                </el-breadcrumb-item>
              </el-breadcrumb>
            </el-form-item>
            <el-form-item>
              <el-select
                v-model="dirQuery.dir"
                clearable
                placeholder="请选择"
                @change="changeDir"
                @clear="
                  () => {
                    dirQuery.dir = undefined;
                  }
                "
                style="width: 150px"
              >
                <el-option
                  v-if="shouldShow"
                  key=".."
                  label="上一级"
                  value=".."
                />
                <el-option
                  v-for="dir in dirList"
                  :key="dir"
                  :label="dir"
                  :value="dir"
                />
              </el-select>
            </el-form-item>
          </el-form>
        </el-form-item>
        <el-form-item label="上传">
          <el-upload
            ref="uploadRef"
            action="#"
            :data="updDate"
            :before-upload="beforeUpd"
            :headers="{ 'x-token': userStore.token }"
            :on-error="uploadError"
            :on-success="uploadSuccess"
            :show-file-list="true"
            :http-request="uploadInChunks"
            multiple
            class="upload-btn"
            v-show="form.option == '0' || form.option == '1'"
            style="width: 300px"
          >
            <el-button type="primary">上传</el-button>
          </el-upload>
          <!-- :http-request="customUpload" -->
          <!-- :multiple="true" -->
          <el-upload
            ref="upload"
            action="#"
            :data="updDate"
            :before-upload="beforeUpd"
            :headers="{ 'x-token': userStore.token }"
            :on-error="uploadError"
            :show-file-list="true"
            :http-request="customUpload"
            class="upload-btn"
            multiple
            v-show="form.option == '2' || form.option == '3'"
            style="width: 300px"
          >
            <el-button type="primary">上传</el-button>
          </el-upload>
          <el-button
            type="primary"
            disabled
            v-show="!['0', '1', '2', '3'].includes(form.option)"
            >上传</el-button
          >
        </el-form-item>
      </el-form>
    </el-dialog>
  </div>
</template>

<script setup>
import {
  getFileList,
  deleteFile,
  editFileName,
  getImg,
  changePermission,
  newFolder,
  getDirList,
} from "@/api/fileUploadAndDownload";
import { computed, ref, reactive, watch, defineProps } from "vue";
import { useRoute, useRouter } from "vue-router";
import { ElMessage, ElMessageBox } from "element-plus";
import { useUserStore } from "@/pinia/modules/user";
import axios from "axios"; // 确保已安装 axios
import { defineEmits } from "vue";

const route = useRoute();
const router = useRouter();
const userStore = useUserStore();
const emit = defineEmits(["on-success"]);
// 后端路径
const path = ref(import.meta.env.VITE_BASE_API);
const props = defineProps({
  dir: {
    type: String,
    required: true,
  },
});
// 文件夹
// 点击选项返回的参数
const dirQuery = ref({});
const currDir = ref("/");
// 文件面包屑数组
const fileDir = ref(
  computed(() => {
    let value = ["根路径"];
    if (!currDir.value || currDir.value === "/") {
      return value;
    }
    // 移除开头的 "/" （如果存在）
    const trimmedDir = currDir.value.startsWith("/")
      ? currDir.value.slice(1)
      : currDir.value;
    // 按照斜杠分割路径，并过滤掉空字符串
    const dirParts = trimmedDir.split("/").filter((part) => part !== "");
    // 将分割后的路径部分添加到 fileDir.value 中
    value.push(...dirParts);
    return value;
  })
);
const shouldShow = ref(computed(() => currDir.value != "/"));
// 文件夹选择列表
const dirList = ref([]);
const getDirListFunc = async () => {
  let param = {
    dirName: currDir.value,
    userName: userStore.userInfo.userName,
  };
  const res = await getDirList(param);
  if (res.code === 0) {
    dirList.value = res.data;
  }
};
getDirListFunc();
// 如果点击了选项会发生什么
const changeDir = () => {
  if (!dirQuery.value.dir) {
    dirQuery.value.dir = "/";
  }
  // 点击 上一级
  if (dirQuery.value.dir == "..") {
    // 删除最后一个斜杠及其后面的所有字符
    currDir.value = currDir.value.replace(/\/[^/]*$/, "");
    if (currDir.value == "") {
      currDir.value = "/";
    }
  } else {
    if (currDir.value != "/") {
      currDir.value += "/";
    }
    currDir.value += dirQuery.value.dir;
  }
  getDirListFunc();
  updDate.value.dir = currDir.value;
  dirQuery.value.dir = undefined;
};
// 暴露给父组件的刷新方法
// 刷新组件
const refreshData = () => {
  currDir.value = props.dir;
};
// 上传弹窗和上传逻辑
const dialogVisible = ref(false);
const openDialog = () => {
  dialogVisible.value = true;
  refreshData();
};
const form = ref({
  option: null,
});
const options = ref([
  {
    label: "私密上传",
    value: "0",
  },
  {
    label: "公开上传",
    value: "1",
  },
  {
    label: "文件夹上传(私密)",
    value: "2",
  },
  {
    label: "文件夹上传(公开)",
    value: "3",
  },
]);
const updDate = ref({
  permission: false,
  userName: undefined,
  dir: undefined,
});

// 支持文件夹上传
const uploadRef = ref(null);
const handleChange = (v) => {
  switch (v) {
    case "0":
      updDate.value.permission = false;
      delDir();
      break;
    case "1":
      updDate.value.permission = true;
      delDir();
      break;
    case "2":
      updDate.value.permission = false;
      setDir();
      break;
    case "3":
      updDate.value.permission = true;
      setDir();
      break;
  }
};
const upload = ref(null);
const setDir = () => {
  const input = upload.value.$el.querySelector("input");
  input.setAttribute("webkitdirectory", "");
  input.setAttribute("directory", "");
};
const delDir = () => {
  const input = upload.value.$el.querySelector("input");
  input.removeAttribute("webkitdirectory");
  input.removeAttribute("directory");
};
const fullscreenLoading = ref(false);
const checkFile = (file) => {
  // fullscreenLoading.value = true
  // const isJPG = file.type === 'image/jpeg'
  // const isPng = file.type === 'image/png'
  // const isLt2M = file.size / 1024 / 1024 < 0.5
  // if (!isJPG && !isPng) {
  //   ElMessage.error('上传图片只能是 jpg或png 格式!')
  //   fullscreenLoading.value = false
  // }
  // if (!isLt2M) {
  //   ElMessage.error('未压缩的上传图片大小不能超过 500KB，请使用压缩上传')
  //   fullscreenLoading.value = false
  // }
  // return (isPng || isJPG) && isLt2M
  fullscreenLoading.value = true;
  const isJPG = file.type === "image/jpeg";
  const isPng = file.type === "image/png";
  const isLt2M = file.size / 1024 / 1024 / 1024 < 0.5;
  // if (!isJPG && !isPng) {
  //   ElMessage.error('上传图片只能是 jpg或png 格式!')
  //   fullscreenLoading.value = false
  // }
  // if (!isLt2M) {
  //   ElMessage.error('未压缩未见上传文件大小不能超过 500KB，请使用压缩上传')
  //   fullscreenLoading.value = false
  // }
  // return  isLt2M
  return true;
};
const beforeUpd = (file) => {
  updDate.value.userName = userStore.userInfo.userName;
  updDate.value.dir = currDir.value;
  updDate.value.fileSize = file.size;
  return checkFile(file);
};
const uploadSuccess = (res) => {
  //const { data } = res
  // if (data.file) {
  //   emit('on-success', data.file.url)
  // }
  if (!res) return;
  const { data } = res;
  if (data.file) {
    emit("on-success", data.file.url);
    // setTimeout(() => {
    //   getTableData();
    // }, 500);
    ElMessage({
      message: "上传成功！",
      type: "success",
    });
    dialogVisible.value = false;
  }
};
const uploadError = () => {
  ElMessage({
    type: "error",
    message: "上传失败",
  });
  fullscreenLoading.value = false;
};
// 点击文件夹面包屑执行函数
const handleCrumbClick = (item, index) => {
  if (index == 0) {
    currDir.value = "/";
  } else {
    // 构建新的 dir 路径
    currDir.value = currDir.value
      .split("/")
      .slice(0, index + 1)
      .join("/");
  }
  console.log(currDir.value);
  getDirListFunc();
};
// 自定义上传方法
const uploadSingle = async (options) => {
  const { file, onProgress, onSuccess, onError, data } = options;
  const task = { file, onProgress, onSuccess, onError, data };
  const formData = new FormData();
  formData.append(`file`, task.file);
  formData.append(`permission`, data.permission);
  formData.append(`userName`, data.userName);
  formData.append(`dir`, data.dir);
  try {
    await axios.post(`${path.value}/fileUploadAndDownload/upload`, formData, {
      headers: {
        "Content-Type": "multipart/form-data",
        "x-token": userStore.token,
      },
      onUploadProgress: (progressEvent) => {
        const percentCompleted = Math.round(
          (progressEvent.loaded * 100) / progressEvent.total
        );
        task.onProgress({ percent: percentCompleted });
      },
    });
    emit("on-success");
    ElMessage({
      message: "上传成功！",
      type: "success",
    });
    dialogVisible.value = false;
  } catch (error) {
    // 处理上传错误
    task.onError(error);
  }
};

const uploadInChunks = async (options) => {
  const { file, onProgress, onSuccess, onError, data } = options;
  const task = { file, onProgress, onSuccess, onError, data };
  const chunkSize = 1024 * 1024 * 500; // 500MB per chunk
  // 总分片数
  const chunks = Math.ceil(file.size / chunkSize);
  let currentChunk = 0;
  const uploadNextChunk = async () => {
    console.log("uploadNextChunk");
    const start = currentChunk * chunkSize;
    const end = Math.min(file.size, start + chunkSize);
    const chunk = file.slice(start, end);
    const formData = new FormData();
    formData.append("file", chunk, file.name);
    formData.append("chunk", currentChunk);
    formData.append("chunks", chunks);
    formData.append(`permission`, data.permission);
    formData.append(`userName`, data.userName);
    formData.append(`dir`, data.dir);
    formData.append(`fileSize`, data.fileSize);
    try {
      await axios.post(
        `${path.value}/fileUploadAndDownload/uploadChunk`,
        formData,
        {
          headers: {
            "Content-Type": "multipart/form-data",
            "x-token": userStore.token,
          },
          onUploadProgress: (progressEvent) => {
            let percentCompleted = Math.round(
              (progressEvent.loaded * 100) / (progressEvent.total * chunks)
            );
            percentCompleted =percentCompleted+ Math.round((100 * currentChunk) / chunks);
            task.onProgress({ percent: percentCompleted });
          },
        }
      );
      currentChunk++;
      if (currentChunk < chunks) {
        await uploadNextChunk();
        return;
      }
      emit("on-success");
      ElMessage({
        message: "上传成功！",
        type: "success",
      });
      dialogVisible.value = false;
    } catch (error) {
      // 处理上传错误
      task.onError(error);
    }
  };
  await uploadNextChunk(); // 开始上传
};

let uploadTimer = null;
const fileQueue = ref([]);
const batchSize = 5; // 每批上传的文件数量
// 每上传一个文件就会走这个方法
const customUpload = async (options) => {
  console.log(options);
  const { file, onProgress, onSuccess, onError, data } = options;
  // 将文件添加到队列
  fileQueue.value.push({ file, onProgress, onSuccess, onError, data });
  if (uploadTimer != null) {
    return;
  }
  // 设置新的定时器
  uploadTimer = setTimeout(() => {
    uploadBatch(data);
  }, 100);
};
const uploadBatch = async (data) => {
  console.log("uploadBatch");
  // 从0开始删除x个元素
  const batch = fileQueue.value.splice(0, batchSize);
  const formData = new FormData();
  batch.forEach((item, index) => {
    formData.append(`file${index}`, item.file);
    // 确保传递文件大小参数
    formData.append(`fileSize${index}`, item.data.fileSize);
  });
  formData.append(`permission`, data.permission);
  formData.append(`userName`, data.userName);
  formData.append(`dir`, data.dir);
  formData.append(`count`, batchSize);
  try {
    const response = await axios.post(
      `${path.value}/fileUploadAndDownload/batchUpload`,
      formData,
      {
        headers: {
          "Content-Type": "multipart/form-data",
          "x-token": userStore.token,
        },
        onUploadProgress: (progressEvent) => {
          const percentCompleted = Math.round(
            (progressEvent.loaded * 100) / progressEvent.total
          );
          batch.forEach((item) =>
            item.onProgress({ percent: percentCompleted })
          );
        },
      }
    );
    // 如果队列中还有文件，继续上传下一批
    if (fileQueue.value.length > 0) {
      await uploadBatch(data);
    }
    emit("on-success");
    ElMessage({
      message: "上传成功！",
      type: "success",
    });
    dialogVisible.value = false;
  } catch (error) {
    // 处理上传错误
    batch.forEach((item) => item.onError(error));
  }
};

watch(props.dir, (dir) => {
  currDir.value = dir;
});
watch(currDir.value, (dir) => {
  getDirListFunc();
});
</script>

<script>
export default {
  name: "UploadCommon",
  methods: {},
};
</script>

<style scoped>
.demo-progress .el-progress--line {
  margin-bottom: 15px;
  max-width: 600px;
}
</style>